import os

import pygame
from pygame import K_DOWN, KEYUP, KEYDOWN

from PyPixelCore.Setting import *
from PyPixelCore.block.BaseBlock import BaseBlock
from PyPixelCore.group.BaseGroup import BaseGroup


def simplify_update(self):
    pass


def base_draw(self, surf):  # 需要改进
    surf.blit(self.image, self.rect)

    if show_rect_collision:
        # pygame.draw.rect(surf, Color_type.RED, self.rect, width=3)
        pygame.draw.rect(surf, Color_type.BLACK, self.collision_rect, width=collision_surface_width)
        pygame.draw.rect(surf, Color_type.RED, self.rect, width=block_surface_width)

        # pygame.draw.circle(surf, Color_type.RED, self.rect.center, 50, width=2)
        # pygame.draw.line(surf, Color_type.RED, self.rect.bottomleft, self.rect.bottomright, width=4)
        # pygame.draw.polygon(surf, Color_type.RED, [(1, 1), (27, 90), (111, 111)], width=3)
        # pygame.draw.arc(surf, Color_type.RED, self.rect, 0, 5, width=100)
        # pygame.draw.aalines(surf, Color_type.RED, False, [(1, 1), (27, 90), (111, 111)], blend=1)


"""
    Panel --> BaseBlock(继承有问题,直接继承按钮或许会更好,通过点击panel的事件同时代理进行按钮点击事件和浮动事件)
    一个界面,维护着各种按钮, 块等控件
    可以在特定时间, 特定地点展示出来的画布
    
    **由于存在大小改变之内的事件,每次脏绘制都等于重绘,严重影响绘制效率
    功能:
        不支持panel的嵌套
        通过脏精灵更新
        维护内部精灵组
        支持焦点
        支持帧动画

"""


class Panel(BaseBlock):
    def __init__(self,
                 point_x,
                 point_y,
                 width,
                 height,
                 border_width=3,
                 layer=0,
                 is_alpha=False,
                 border_color=Color_type.BLACK,
                 bk_color=Color_type.WHITE):
        super().__init__(layer)
        self._original_border_color = border_color  # 焦点事件后使用
        self.is_focus = False  # 判断是否是焦点以执行鼠标事件
        self.rect.x = point_x
        self.rect.y = point_y
        self.update_func = simplify_update
        self.timer_update_func = simplify_update
        self.timer_arr = []
        self.point_x = point_x
        self.point_y = point_y
        self.width = width
        self.height = height
        self.border_width = border_width
        self.is_alpha = is_alpha
        self.is_show = True
        self._type = Block_type.panel  # 绘制成块

        self.focus_animation_do = base_focus_animation
        self.leave_focus_animation_do = base_leave_focus_animation
        self.focus_motion_animation_do = base_motion_animation
        self.mouse_up_do = base_mouse_up_do

        self.wheel_down_animation_do = pass_func
        self.wheel_up_animation_do = pass_func

        # 为了支持panel进行嵌套操作, 增加碰撞域(目前不支持嵌套panel)
        # self.collision_rect = self.rect

        self.bk_image = self.image  # 背景的备份,减少计算
        self.bk_color = bk_color
        self.border_color = border_color
        self.sprites_group = BaseGroup()  # 用于维护自己内部的组
        # self.sprites_layout_pos = []  # 用于维护每个内置精灵的布局  [(x, y), (x2, y2), ...]

        self.event_dict = {}  # 存储键盘的事件字典,通过键盘对panel中的块进行操作{key:[down_func, up_func]}

        self._reload_image_first()

    def change_point_x_y(self, point_x=None, point_y=None):  # 不建议移动画布panel，不仅麻烦，而且没有太大的意义
        offset_x = 0
        offset_y = 0
        if point_x is not None:
            offset_x = point_x - self.rect.x
            self.rect.x = point_x
        if point_y is not None:
            offset_y = point_y - self.rect.y
            self.rect.y = point_y
        for sprite in self.sprites_group.sprites():
            # if sprite.type == Block_type.panel:
            #     sprite.change_point_x_y(point_x, point_y)
            # else:
            #     sprite.collision_rect.x += offset_x
            #     sprite.collision_rect.y += offset_y
            if sprite.type == Block_type.panel: continue
            sprite.collision_rect.x += offset_x
            sprite.collision_rect.y += offset_y
        self.is_dirty = True

    def change_point_by_offset(self, offset_x, offset_y):  # 不建议移动画布panel，不仅麻烦，而且没有太大的意义
        self.rect.x += offset_x
        self.rect.y += offset_y
        for sprite in self.sprites_group.sprites():
            if sprite.type == Block_type.panel: continue
            sprite.collision_rect.x += offset_x
            sprite.collision_rect.y += offset_y
        self.is_dirty = True

    def kill(self):
        super().kill()
        for each_sprite in self.sprites_group:
            each_sprite.kill()

    def temp_kill(self):
        temp_sprite = self.sprites_group.copy()
        self.kill()
        print(temp_sprite.sprites())
        self.sprites_group = temp_sprite

    def add_sprites(self, *sprites):
        for sprite in sprites:
            if sprite is None: continue
            if sprite.type == Block_type.panel:
                for sprite_inner in sprite.sprites_group.sprites():
                    self.add_sprites(sprite_inner)
                sprite.rect.x += self.point_x
                sprite.rect.y += self.point_y
                self.sprites_group.add(sprite)
            else:
                # if sprite.type in []
                sprite.collision_rect.x += self.point_x
                sprite.collision_rect.y += self.point_y
                self.sprites_group.add(sprite)

        self.is_dirty = True
        self.reload_image()

    def _reload_image_first(self):
        self.is_dirty = False
        # 重新更新图像
        if self.is_alpha:
            self.image = pygame.Surface((self.width + 2*self.border_width, self.height + 2*self.border_width)).convert_alpha()
        else:
            self.image = pygame.Surface((self.width + 2*self.border_width, self.height + 2*self.border_width))
        self.image.fill(self.bk_color)
        self.rect.size = self.image.get_rect().size

        self.bk_image = self.image.copy()

        # 绘制
        for sprite in self.sprites_group.sprites():
            sprite.draw(self.image)

        # 绘制方框到主图上
        if self.border_width > 0:
            pygame.draw.rect(self.image, self.border_color, (0, 0, self.rect.width, self.rect.height),
                             width=self.border_width)
            pygame.draw.rect(self.bk_image, self.border_color, (0, 0, self.rect.width, self.rect.height),
                             width=self.border_width)

    def _reload_bk_image(self):
        # 重新更新背景图像
        if self.is_alpha:
            self.bk_image = pygame.Surface((self.width + 2*self.border_width, self.height + 2*self.border_width)).convert_alpha()
        else:
            self.bk_image = pygame.Surface((self.width + 2*self.border_width, self.height + 2*self.border_width))
        self.bk_image.fill(self.bk_color)
        self.rect.size = self.bk_image.get_rect().size


    def reload_image(self):
        for sprite in self.sprites_group.sprites():
            if sprite.is_dirty:
                self.is_dirty = True
            if sprite.is_show:
                sprite.update()
        if not self.is_dirty:
            return

        self.is_dirty = False
        # 重新更新图像
        self.image = self.bk_image.copy()
        self.rect.size = self.image.get_size()
        # 绘制
        for sprite in self.sprites_group.sprites():
            sprite.draw(self.image)

        # 绘制边框
        if self.border_width > 0:
            pygame.draw.rect(self.image, self.border_color, (0, 0, self.rect.width, self.rect.height),
                             width=self.border_width)

    def set_color_not_None(self, border_color=None, bk_color=None):
        if border_color is not None:
            self.border_color = border_color
        if bk_color is not None:
            self.bk_color = bk_color
            self._reload_bk_image()
        self.is_dirty = True

    def update(self):
        if not self.is_show:
            return
        # 帧函数的调用
        if self.update_func:
            self.update_func(self)
        # 帧计时器函数的调用
        if self.timer_arr:
            for timer_group in self.timer_arr:
                timer_group[0].next_frame()
                if timer_group[0].is_end:
                    timer_group[1](self)
                    if timer_group[0].type == 0:  # 一次性循环则删除不参与reset
                        self.timer_arr.remove(timer_group)
                    else:
                        timer_group[0].reset()
        self.reload_image()

    def draw(self, surf):
        surf.blit(self.image, self.rect)

    def set_frame_animation(self, func):
        self.update_func = func

    def set_timer_animation(self, timer, func):
        self.timer_arr.append([timer, func])

    def delete_timer_animation(self, func):
        for each_func in self.timer_arr:
            if each_func[1] == func:
                self.timer_arr.remove(each_func)

    def clean_timer(self):
        self.timer_arr = []

    def focus_animation(self, pos):
        self.focus_animation_do(self,pos)


    def leave_focus_animation(self, pos):
        self.is_focus = False
        self.leave_focus_animation_do(self,pos)

    def wheel_down_animation(self):
        self.wheel_down_animation_do(self)

    def wheel_up_animation(self):
        self.wheel_up_animation_do(self)

    def add_key_event(self, key_name, key_down_func, key_up_func=None):
        if key_up_func is not None:
            self.event_dict[key_name] = [key_down_func, key_up_func]
        else:
            self.event_dict[key_name] = [key_down_func, None]

    def reset_key_event(self, key_name, key_down_func=None, key_up_func=None):
        if key_name not in self.event_dict:
            self.event_dict[key_name] = [None,None]
        if key_down_func is not None:
            self.event_dict[key_name][0] = key_down_func
        if key_up_func is not None:
            self.event_dict[key_name][1] = key_up_func

    def do_key_event(self, event:pygame.event.Event):
        if event.key in self.event_dict:
            if event.type == KEYDOWN:
                if self.event_dict[event.key][0]:
                    self.event_dict[event.key][0](self)
            if event.type == KEYUP:
                if self.event_dict[event.key][1]:
                    self.event_dict[event.key][1](self)


def base_focus_animation(self,pos):
    if self.is_focus:
        return
    self.is_focus = True
    self.border_color = Color_type.BRIGHT_BLUE
    self.is_dirty = True

def base_leave_focus_animation(self, pos):
    self.border_color = self._original_border_color
    self.is_dirty = True

def base_motion_animation(self, pos):
    pass

def base_mouse_up_do(self):
    pass

def pass_func(self):
    pass

